package de.jmda.gen.impl;

import java.util.Collection;
import java.util.LinkedList;

import org.apache.commons.lang.StringUtils;

import de.jmda.gen.CompoundGenerator;
import de.jmda.gen.Generator;
import de.jmda.gen.GeneratorException;

/**
 * Maintains a <code>componentSeparator</code> (see {@link
 * #getComponentSeparator()}) and provides a {@link #generate()} implementation.
 * <p>
 * The class is abstract because it is intended that sub classes take the
 * responsibility for maintaining generator components and provide individual
 * {@link #getGeneratorComponents()} implementations.
 *
 * @author roger.jmda@gmail.com
 */
public abstract class AbstractCompoundGenerator
		extends DefaultGenerator
		implements CompoundGenerator
{
	/**
	 * useful for setting {@link #componentSeparator} via {@link
	 * #setComponentSeparator(String)}
	 */
	public final static String DOUBLE_LINE_SEPARATOR =
			StringUtils.repeat(System.lineSeparator(), 2);

	private String componentSeparator;
	
	/**
	 * Consecutively calls the {@link #generate()} method of each {@link
	 * Generator} in {@link #getGeneratorComponents()} and joins their return
	 * values with {@link #getComponentSeparator()} to assemble the overall
	 * generation result. Their return values will only be joined if they are not
	 * <code>null</code> and not empty (<code>length != 0</code>)!
	 * <p>
	 * Override {@link #getGeneratorComponents()} and / or {@link
	 * #getComponentSeparator()} to modify the result of this default
	 * implementation.
	 *
	 * @see de.jmda.gen.Generator#generate()
	 */
	@Override
	public StringBuffer generate() throws GeneratorException
	{
		Collection<StringBuffer> parts = new LinkedList<StringBuffer>();

		for (Generator generator : getGeneratorComponents())
		{
			// maybe a generator is deactivated by being set to null
			if (generator != null)
			{
				StringBuffer part = generator.generate();

				// add only non null and non empty parts
				if (part != null)
				{
					if (part.length() > 0)
					{
						parts.add(part);
					}
				}
			}
		}

		return
				getLineIndenter().indent(
						new StringBuffer(StringUtils.join(parts, getComponentSeparator())));
	}

	/**
	 * @return {@link #componentSeparator}, if <code>null</code> it will be lazily
	 *         initialised to <code>""</code>.
	 */
	@Override
	public String getComponentSeparator()
  {
		if (componentSeparator == null)
		{
			componentSeparator = "";
		}

		return componentSeparator;
  }

	public void setComponentSeparator(String componentSeparator)
	{
		this.componentSeparator = componentSeparator;
	}
}